import numpy as np
import plotly.graph_objects as go
from plotly.subplots import make_subplots
# Define the vector field F(x, y, z) = (yz, xz, xy + exp(-x^2 - y^2 - z^2))
def vector_field(x, y, z):
"""Vector field F(x, y, z) = (yz, xz, xy + exp(-x^2 - y^2 - z^2))"""
= y * z
F_x = x * z
F_y = x * y + np.exp(-(x**2) - y**2 - z**2)
F_z return np.array([F_x, F_y, F_z])
# Calculate Gradient (for visualization purposes)
def divergence(x, y, z, h=1e-5):
"""Calculate the divergence of the vector field using finite differences."""
= (vector_field(x + h, y, z)[0] - vector_field(x - h, y, z)[0]) / (2 * h)
dFxdx = (vector_field(x, y + h, z)[1] - vector_field(x, y - h, z)[1]) / (2 * h)
dFydy = (vector_field(x, y, z + h)[2] - vector_field(x, y, z - h)[2]) / (2 * h)
dFzdz return dFxdx + dFydy + dFzdz
def curl(x, y, z, h=1e-5):
"""Calculate the curl of the vector field using finite differences."""
= (vector_field(x, y + h, z)[2] - vector_field(x, y - h, z)[2]) / (2 * h)
dFz_dy = (vector_field(x, y, z + h)[1] - vector_field(x, y, z - h)[1]) / (2 * h)
dFy_dz = (vector_field(x, y, z + h)[0] - vector_field(x, y, z - h)[0]) / (2 * h)
dFx_dz = (vector_field(x + h, y, z)[2] - vector_field(x - h, y, z)[2]) / (2 * h)
dFz_dx = (vector_field(x + h, y, z)[1] - vector_field(x - h, y, z)[1]) / (2 * h)
dFy_dx = (vector_field(x, y + h, z)[0] - vector_field(x, y - h, z)[0]) / (2 * h)
dFx_dy
= dFz_dy - dFy_dz
curl_x = dFx_dz - dFz_dx
curl_y = dFy_dx - dFx_dy
curl_z return np.array([curl_x, curl_y, curl_z])
# Generate 3D grid points
= np.linspace(-2, 2, 20) # Adjust the range for better visualization
x_vals = np.linspace(-2, 2, 20)
y_vals = np.linspace(-2, 2, 20)
z_vals = np.meshgrid(x_vals, y_vals, z_vals)
X, Y, Z
# Initialize arrays for vector field, divergence, and curl
= np.zeros((X.size, 3))
vector_values = np.zeros(X.size)
divergence_values = np.zeros((X.size, 3))
curl_vectors
# Calculate field values
for i in range(X.size):
= X.flatten()[i], Y.flatten()[i], Z.flatten()[i]
x, y, z
# Calculate Vector Field
= vector_field(x, y, z)
vec = vec
vector_values[i]
# Calculate Divergence
= divergence(x, y, z)
div = div
divergence_values[i]
# Calculate Curl
= curl(x, y, z)
crl = crl
curl_vectors[i]
# Prepare Plotly figures
= make_subplots(
fig =1,
rows=3,
cols=[[{"type": "scatter3d"}, {"type": "scatter3d"}, {"type": "scatter3d"}]],
specs=["Vector Field", "Divergence", "Curl"],
subplot_titles
)
# Vector Field Plot
fig.add_trace(
go.Cone(=X.flatten(),
x=Y.flatten(),
y=Z.flatten(),
z=vector_values[:, 0],
u=vector_values[:, 1],
v=vector_values[:, 2],
w="absolute",
sizemode=0.5,
sizeref="Blues",
colorscale
),=1,
row=1,
col
)
# Divergence Field Plot
fig.add_trace(
go.Scatter3d(=X.flatten(),
x=Y.flatten(),
y=Z.flatten(),
z="markers",
mode=dict(
marker=4,
size=divergence_values,
color="Reds",
colorscale=dict(title="Divergence"),
colorbar
),
),=1,
row=2,
col
)
# Curl Field Plot
fig.add_trace(
go.Cone(=X.flatten(),
x=Y.flatten(),
y=Z.flatten(),
z=curl_vectors[:, 0],
u=curl_vectors[:, 1],
v=curl_vectors[:, 2],
w="absolute",
sizemode=0.5,
sizeref="Greens",
colorscale
),=1,
row=3,
col
)
# Update Layout
fig.update_layout(=600,
height=1800,
width="3D Visualization of Vector Field, Divergence, and Curl",
title_text=False,
showlegend
) fig.show()
Nabla
In \(\mathbb{R}^3\) the nabla operator is defined as: \[ \nabla=\mathbf{e}_x \frac{\partial}{\partial x}+\mathbf{e}_y \frac{\partial}{\partial y}+\mathbf{e}_z \frac{\partial}{\partial z}=\left[\frac{\partial}{\partial x}, \frac{\partial}{\partial y}, \frac{\partial}{\partial z}\right] \] where \(\mathbf{e}_x\), \(\mathbf{e}_y\) and \(\mathbf{e}_z\) are the unit vectors in the \(x\), \(y\) and \(z\) directions respectively, i.e. standard basis.
Gradient, Divergence and Curl
The gradient of a scalar field \(f(x,y,z)\) is a vector field defined as: \[ \nabla f = \left[\frac{\partial f}{\partial x}, \frac{\partial f}{\partial y}, \frac{\partial f}{\partial z}\right] \]
The divergence of a vector field \(\mathbf{F}(x,y,z)\) is a scalar field defined as: \[ \nabla \cdot \mathbf{F} = \frac{\partial F_x}{\partial x} + \frac{\partial F_y}{\partial y} + \frac{\partial F_z}{\partial z} \]
The curl of a vector field \(\mathbf{F}(x,y,z)\) is a vector field defined as a determinant: \[ \nabla \times \mathbf{F} = \left[\frac{\partial}{\partial x}, \frac{\partial}{\partial y}, \frac{\partial}{\partial z}\right] \times \begin{vmatrix} \mathbf{e}_x & \mathbf{e}_y & \mathbf{e}_z \\ \frac{\partial}{\partial x} & \frac{\partial}{\partial y} & \frac{\partial}{\partial z} \\ F_x & F_y & F_z \end{vmatrix} \]
All these operators are linear, which are important properties for solving differential equations, that we know the linear combination of two solutions is also a solution.
Linear Properties of Nabla
The nabla operator has the following linear properties, such that for any scalar field \(f\) and \(g\) and any constant \(c\), for gradient: \[ \nabla(f+g)=\nabla f+\nabla g\\ \nabla(c f)=c \nabla f \]